from ability.serializer.serializers import ImageSerializer
from requests import models
from rest_framework import  serializers
from ability.models import Environment, Experiment, InsEvent, LogStashFile, Order, Report, Instance,StudentExperiment
from ability.cloud import CloudInstance, CloudImage
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from datetime import datetime
import time

class StudentCountMixin():

    def get_student_count(self, obj):
        return obj.student.count()

class ExperimentListSerializer(serializers.HyperlinkedModelSerializer, StudentCountMixin):
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    student_count = serializers.SerializerMethodField()
    # report_count = serializers.SerializerMethodField()
    # read_report_count = serializers.SerializerMethodField()
    live_ins_count = serializers.SerializerMethodField()
    experiment_env_create_time = serializers.SerializerMethodField()

    class Meta:
      model = Experiment
      # fields = ['id', 'experiment_name','describe','experiment_env_create_time','student_count', 'report_count', 'read_report_count', 'create_time', 'status', 'price', 'intro','live_ins_count']
      fields = ['id', 'experiment_name','experiment_env_create_time','student_count', 'create_time', 'status', 'live_ins_count']

    # def get_report_count(self, obj):
    #   return Report.objects.filter(experiment=obj).count()

    def get_experiment_env_create_time(self, obj):
      if obj.environment_id in ['',None]:
        return '--'
      return Environment.objects.filter(id=obj.environment_id).first().create_time.strftime("%Y-%m-%d %H:%M:%S")

    # def get_read_report_count(self, obj):
    #   return Report.objects.filter(experiment=obj, score__gte=0).count()

    def get_live_ins_count(self, obj):

        return Instance.objects.filter(environment_id=obj.environment_id).exclude(status='C').count()

    def get_student_count(self, obj):
        return StudentExperiment.objects.filter(experiment = obj).values('student_id').distinct().count()

class ExperimentEditSerializer(serializers.ModelSerializer):
  
  class Meta:
    model = Experiment
    fields = ['id', 'experiment_name', 'type', 'price', 'duration']


class ExperimentEditDescSerializer(serializers.ModelSerializer):
  
  class Meta:
    model = Experiment
    fields = ['describe', 'detail_type', 'intro']

class EnvironmentSerializer(serializers.ModelSerializer):
    create_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    images = serializers.SerializerMethodField()
    experiment_type = serializers.SerializerMethodField()

    class Meta:
        model = Environment
        fields = ['id', 'images', 'subnet_name', 'cidr_block', 'is_open', 'create_time', 'security_group','experiment_type']

    def get_images(self, obj):
        res = obj.image.all()
        if self.get_experiment_type(obj=obj) == "double":
            if len(res) == 1:
               return [res[0].image_name,res[0].image_name]
            else:
               experiment_primary_id = obj.experiment.primary_image_id
               list = []
               cii =''
               for image in res:
                   if int(image.id) == int(experiment_primary_id):
                       list.append(image.image_name)
                   else:
                       cii=image.image_name
               list.append(cii)
               return  list
        return [image.image_name for image in res]

    def get_experiment_type(self, obj):
        experiment = obj.experiment
        return experiment.experiment_type if experiment is not None else None

    def get_experiment_id(self, obj):
        experiment = obj.experiment
        return experiment.id if experiment is not None else None

class InstanceListSerializer(serializers.ModelSerializer):
    instance_name = serializers.CharField(source='name')
    status = serializers.SerializerMethodField()
    username = serializers.CharField(source='student.user.real_name',required=False)
    studentid = serializers.CharField(source='student.studentID',required=False)
    images = serializers.CharField(source='image.image_name')
    class Meta:
        model = Instance
        fields = ('id','environment_id','instance_name','instanceId','images', 'ip_address', 'status', 'studentid', 'username')

    def get_status(self, obj):
        instance = CloudInstance()
        ins = instance.DescribeInstance(obj.instanceId)
        if ins is None:
            return "--"
        return ins.InstanceState


    # def get_status(self, obj):
    #     return obj.get_status_display()

    def get_vnc_url(self, obj):
        cloudInstance = CloudInstance()
        whileCount = 0
        vncUrl = ''
        while 1:
            if whileCount > 50:
                raise Exception('实例开机失败')
            try:
                vncUrl = cloudInstance.DescribeInstanceVncUrl(obj.instanceId)
                break
            except TencentCloudSDKException as e:
                if e.code == 'InvalidInstanceId.NotFound':
                    obj.status = 'C'
                    obj.save()
                    raise Exception('实例开机失败2')
                if e.code == 'UnsupportedOperation.InstanceStateStopped':
                    # todo 开机
                    cloudInstance.start([obj.instanceId])
                whileCount += 1
                time.sleep(2)
            except Exception as e:
                whileCount += 1
                time.sleep(2)
        return vncUrl

class TeacherReportListSerializer(serializers.ModelSerializer):
    
    report_title = serializers.CharField(source='title')
    belong_experiment = serializers.CharField(source='experiment.experiment_name')
    # report_status = serializers.SerializerMethodField()
    # studentID = serializers.CharField(source='student.studentID')
    username = serializers.CharField(source='student.user.username')
    submit_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    start_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")
    student_join_count = serializers.SerializerMethodField()

    class Meta:
      model = Report
      fields = ('id', 'report_title', 'belong_experiment', 'username', 'submit_time', 'start_time','student_join_count')

    def get_student_join_count(self, obj):
      return  Instance.objects.filter(student=obj.student,environment=obj.experiment.environment).count()

    # def get_report_status(self, obj):
    #   return "已评分" if obj.score > 0 else "未评分"
    
    # def get_order_time(self, obj):
    #   try:
    #     order = Order.objects.filter(user=obj.student.user, order_type=Order.ORDER_TYPE_EXPERIMENT, product_id=obj.experiment.id, status=Order.STATUS_PAYED).first()
    #     return order.pay_at.strftime("%Y-%m-%d %H:%M:%S")
    #   except Order.DoesNotExist:
    #     return ''

class ReportListSerializer(serializers.ModelSerializer):
    
    report_title = serializers.CharField(source='title')
    belong_experiment = serializers.CharField(source='experiment.experiment_name')
    report_status = serializers.SerializerMethodField()
    studentID = serializers.CharField(source='student.studentID')
    username = serializers.CharField(source='student.user.real_name')

    class Meta:
        model = Report
        fields = ('id', 'report_title', 'belong_experiment', 'report_status', 'studentID', 'username', 'score')

    def get_report_status(self, obj):
        return "已评分" if obj.score > 0 else "未评分"

class InsEventCreateSerializer(serializers.ModelSerializer):

    class Meta:
        model = InsEvent
        fields = '__all__'

class LogstashSerializer(serializers.ModelSerializer):

    class Meta:
        model = LogStashFile
        fields = ['id', 'message']

